#include "../../include/DBUtil.hpp"
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset_metadata.h>
#include <json/reader.h>
#include <json/writer.h>

using namespace std;
using namespace Json;
using namespace sql;

int DBUtil::execute(const string& sql) {
    // 从连接池获取连接（自动管理生命周期）
	auto conn = ConnectionPool::getInstance()->getConnection();
    if (!conn) 		return -1;      // 失败给-1  affected {} rows

    try {
        auto stmt = conn->createStatement();
        return stmt->executeUpdate(sql);  // 返回受影响行数
    } catch (const sql::SQLException& e) {
        cerr << "SQL执行错误: " << e.what() 
             << " (错误状态码: " << e.getErrorCode() 
             << ", SQL状态: " << e.getSQLState() << ")" << endl;
        return -1;
    }
}

// 执行查询并返回JSON数组
Value DBUtil::query(const string& sql) {
    // arrayValue,    ///< array value (ordered list)  enum Json::ValueType::arrayValue = 6
	Value ans(arrayValue);      // 创建JSON数组
	auto conn = ConnectionPool::getInstance()->getConnection();
	if (!conn)	return ans;

	try {
		auto stmt = conn->createStatement();
        auto res = stmt->executeQuery(sql);
        auto meta = res->getMetaData();     // 获取结果集元数据
        int cols = meta->getColumnCount();

		// 遍历结果集
		while (res->next()) {
            Value row;      // 每一行都要成JSON对象 对应类型
            for (int i = 1; i <= cols; ++i) {
                string colName = meta->getColumnLabel(i);
                
                // 根据类型转换字段值
                switch (meta->getColumnType(i)) {
                    case sql::DataType::INTEGER:
                        row[colName] = res->getInt(i);
                        break;
                    case sql::DataType::DOUBLE:
                        row[colName] = static_cast<double>(res->getDouble(i));
                        break;
                    // 一些MySQL驱动程序使用TINYINT或BIT来表示布尔值
                    case sql::DataType::BIT:
                        row[colName] = static_cast<bool>(res->getBoolean(i));
                        break;
                    default:
                    // 其他类型转为字符串
                        row[colName] = std::string(res->getString(i));
                }
            }
			ans.append(row);
		}
	} catch (const sql::SQLException& e) {
		cerr << "SQL查询错误: " << e.what() << endl;
	}
	return ans;
}

// 事务类构造
DBUtil::Transaction::Transaction() {
    // 构造时获取连接并开启事务
    conn_ = ConnectionPool::getInstance()->getConnection();
    if (!conn_ || conn_->isClosed()) {  // 双重检查
        throw runtime_error("事务初始化失败：连接无效或已关闭");
    }
    conn_->setAutoCommit(false);
    active_ = true;
}

DBUtil::Transaction::~Transaction() {
    // 析构时检查未提交的事务自动回滚
    // 类似git操作
    if (active_ && conn_) {
        try {
            conn_->rollback();
        } catch (...) {
            cerr << "事务回滚失败" << endl;
        }
    }
}

bool DBUtil::Transaction::commit() {
	if (!active_ || !conn_)         return false;
    
    try {
        conn_->commit();
        active_ = false;
        return true;
    } catch (const sql::SQLException& e) {
        cerr << "事务提交失败: " << e.what() << endl;
        return false;
    }
}

void DBUtil::Transaction::rollback() { 
	if (active_ && conn_) {
        try {
            conn_->rollback();
            active_ = false;
        } catch (...) {
            cerr << "事务回滚失败" << endl;
        }
    }
}

bool DBUtil::Transaction::execute(const string& sql) {
    if (!active_ || !conn_)         return false;

    try {
        auto stmt = conn_->createStatement();
        return stmt->executeUpdate(sql) > 0;
    } catch (...) {
        return false;
    }
}

Value DBUtil::Transaction::query(const string& sql) {
    // 统一检查前置条件
    if (!active_ || !conn_ || conn_->isClosed()) {
        return Value(arrayValue);
    }

    Value ans(arrayValue);
    try {
        // 使用智能指针自动管理资源
        auto stmt = conn_->createStatement();
        auto res = stmt->executeQuery(sql);
        auto meta = res->getMetaData();
        int cols = meta->getColumnCount();

        while (res->next()) {
            Value row;
            for (int i = 1; i <= cols; ++i) {
                row[meta->getColumnLabel(i)] = Value(string(res->getString(i)));
            }
            ans.append(row);
        }
    } catch (const std::exception& e) {
        // 捕获具体异常并记录日志
        std::cerr << "查询执行失败: " << e.what() << std::endl;
    } catch (...) {
        // 捕获其他未知异常并记录日志
        std::cerr << "查询执行过程中发生了未知错误。" << std::endl;
    }
    
    return ans;
}


/**
 * 可变参数的预处理语句
 * typename... Args：声明可变类型参数包
 * Args&&... args：声明可变参数包（完美转发引用）
 * 
 * 修改说明：
 * 1. 替换不存在的setObject方法为类型特定的set方法
 * 2. 使用lambda+if constexpr实现类型分发
 * 3. 保留原有错误处理机制
 */
template<typename... Args>
int DBUtil::Transaction::ececutePrepared(const string& sql, Args&&... args) {
    if (!active_ || !conn_)         return -1;

    try {
        auto pstmt = conn_->prepareStatement(sql);
        int index = 1;
        
        // 使用lambda和折叠表达式展开参数包（C++17特性）
        // 实现类型自适应的参数绑定
        auto setParam = [&](auto&& arg) {
            using T = std::decay_t<decltype(arg)>;
            if constexpr (std::is_same_v<T, int>) {
                pstmt->setInt(index++, arg);
            } 
            else if constexpr (std::is_same_v<T, std::string>) {
                pstmt->setString(index++, arg);
            }
            else if constexpr (std::is_same_v<T, double>) {
                pstmt->setDouble(index++, arg);
            }
            // 可继续添加其他类型支持...
        };
        
        // 展开参数包
        // 等价于：
        // setParam(arg1);
        // setParam(arg2);
        // ...
        (setParam(std::forward<Args>(args)), ...);

        return pstmt->executeUpdate();
    } catch (...) {
        return -1;
    }
}
